package com.atguigu.srb.core.service.impl;

import com.atguigu.srb.base.asserts.Asserts;
import com.atguigu.srb.base.consts.SrbConsts;
import com.atguigu.srb.base.response.ResponseEnum;
import com.atguigu.srb.base.util.JwtUtils;
import com.atguigu.srb.core.pojo.entity.BorrowInfo;
import com.atguigu.srb.core.mapper.BorrowInfoMapper;
import com.atguigu.srb.core.pojo.entity.Borrower;
import com.atguigu.srb.core.pojo.entity.UserInfo;
import com.atguigu.srb.core.pojo.entity.vo.BorrowInfoVO;
import com.atguigu.srb.core.pojo.entity.vo.BorrowerDetailVO;
import com.atguigu.srb.core.service.*;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 借款信息表 服务实现类
 * </p>
 *
 * @author Atguigu
 * @since 2023-05-26
 */
@Service
public class BorrowInfoServiceImpl extends ServiceImpl<BorrowInfoMapper, BorrowInfo> implements BorrowInfoService {
    @Resource
    UserInfoService userInfoService;
    @Resource
    IntegralGradeService integralGradeService;
    @Resource
    BorrowerService borrowerService;
    @Resource
    DictService dictService;
    @Override
    public void saveBorrowInfo(BorrowInfo borrowInfo, String token) {
        Asserts.assertNotNull(borrowInfo.getAmount(),ResponseEnum.PARAM_ERROR);
        Asserts.assertNotNull(borrowInfo.getBorrowYearRate(),ResponseEnum.PARAM_ERROR);
        Asserts.assertNotNull(borrowInfo.getMoneyUse(),ResponseEnum.PARAM_ERROR);
        Asserts.assertNotNull(borrowInfo.getPeriod(),ResponseEnum.PARAM_ERROR);
        Asserts.assertNotNull(borrowInfo.getReturnMethod(),ResponseEnum.PARAM_ERROR);

        //借款人提交借款申请时：账号必须正常、必须已绑定hfb账户、借款人申请状态已审核通过
        //定义一个业务方法用来对用户的所有状态进行校验
        UserInfo userInfo = userInfoService.checkAccount(token);
        Long userId = userInfo.getId();
        // 添加判断业务   如果当前用户有未完成的借款  不能再申请借款了
        //使用userId 和  status 查询  如果查询到status为1或者2的 借款信息 代表有未完成的
        Asserts.assertNotTrue(this.count(Wrappers.lambdaQuery(BorrowInfo.class)
                .eq(BorrowInfo::getUserId , userId)
                .in(BorrowInfo::getStatus,1,2))>0,ResponseEnum.BORROW_EXISTS_ERROR);

        //校验借款金额是否超过额度
        BigDecimal amount = integralGradeService.getAmount(token);
        //借款金额必须小于等于 允许额度:
        //borrowInfo.getAmount().compareTo(amount)==1 调用compareTo的bigDecimal大
        Asserts.assertNotTrue(borrowInfo.getAmount().compareTo(amount)==1 ,
                ResponseEnum.USER_AMOUNT_LESS_ERROR);
        //一个用户只能有一个进行中的或者申请成功但是未完成的借款

        borrowInfo.setUserId(userId);
        //1：审核中， 2：审核通过， -1：审核不通过
        borrowInfo.setStatus(1);
        this.save(borrowInfo);
    }

    @Override
    public Integer getStatus(String token) {
        Long userId = JwtUtils.getUserId(token);
        //用户申请借款时，一定是按照时间先后顺序来申请
        //查询时间降序排列的第一个借款申请
        BorrowInfo borrowInfo = this.getOne(Wrappers.lambdaQuery(BorrowInfo.class)
                .eq(BorrowInfo::getUserId, userId)
                .select(BorrowInfo::getStatus)
                .orderByDesc(BorrowInfo::getUpdateTime)
                .last("limit 1"));
        //如果borrowInfo不存在，返回0
        return borrowInfo==null?0:borrowInfo.getStatus();
    }

    @Override
    public List<BorrowInfoVO> getBorrowInfoVOs() {
        //可以自定义sql
        //按照时间降序查询所有的借款申请
        List<BorrowInfo> borrowInfos = this.list(Wrappers.lambdaQuery(BorrowInfo.class)
                .orderByDesc(BorrowInfo::getUpdateTime));
        //遍历借款申请集合：为每个借款申请查询userInfo的数据 和其他字段的值
        // 每个借款申请borrowInfo对象 对应一个 BorrowInfoVO对象
        //map(): 可以对遍历的每个对象处理转换为其他类型的对象
        //collect(Collectors.toList()): 将前面处理的结果转为新的List集合
        //filter(表达式): 可以对遍历的对象进行过滤(筛选数据：表达式结果为true数据保留，否则移除)
        List<BorrowInfoVO> borrowInfoVOS = borrowInfos.stream().map(borrowInfo -> {
            return getBorrowInfoVO(borrowInfo);
        }).collect(Collectors.toList());

        return borrowInfoVOS;
    }

    private BorrowInfoVO getBorrowInfoVO(BorrowInfo borrowInfo) {
        BorrowInfoVO borrowInfoVO = new BorrowInfoVO();
        BeanUtils.copyProperties(borrowInfo, borrowInfoVO);
        //查询borrowInfoVO需要的用户姓名和手机号
        Long userId = borrowInfo.getUserId();
        UserInfo userInfo = userInfoService.getById(userId);
        borrowInfoVO.setName(userInfo.getName());
        borrowInfoVO.setMobile(userInfo.getMobile());
        //给borrowInfoVO设置页面显示时需要处理的字符串属性
        borrowInfoVO.getParams().put("period",borrowInfoVO.getPeriod()+"个月");
        borrowInfoVO.getParams().put("borrowYearRate",borrowInfoVO.getBorrowYearRate()+"%");
        borrowInfoVO.getParams().put("status",getBorrowInfoStatus(borrowInfoVO.getStatus()));
        borrowInfoVO.getParams().put("moneyUse",dictService.selectDictNameByDictCodeAndValue(SrbConsts.DICT_CODE_MONEY_USE,
                borrowInfoVO.getMoneyUse()));
        borrowInfoVO.getParams().put("returnMethod",dictService.selectDictNameByDictCodeAndValue(SrbConsts.DICT_CODE_RETURN_METHOD,
                borrowInfoVO.getReturnMethod()));
        return borrowInfoVO;
    }

    @Override
    public Map<String, Object> getBorrowInfoById(String id) {
        //根据借款申请id查询 借款申请的详情数据
        BorrowInfo borrowInfo = this.getById(id);
        BorrowInfoVO borrowInfoVO = getBorrowInfoVO(borrowInfo);
        //查询借款人详情
        Long userId = borrowInfo.getUserId();
        //根据用户id获取借款人id
        Borrower borrower = borrowerService.getOne(Wrappers.lambdaQuery(Borrower.class)
                .eq(Borrower::getUserId, userId));
        BorrowerDetailVO borrowerDetailVO = borrowerService.getBorrowerDetailById(borrower.getId().toString());

        Map<String, Object> map = new HashMap<String,Object>();
        map.put("borrowInfoVO",borrowInfoVO);
        map.put("borrowerDetailVO",borrowerDetailVO);
        return map;
    }

    private String getBorrowInfoStatus(Integer status){
        String statusStr;
        //状态（0：未提交，1：审核中， 2：审核通过， -1：审核不通过, 3: 借款已关闭）
        switch (status){
            case 0:
                statusStr = "未提交";
                break;
            case 1:
                statusStr = "审核中";
                break;
            case 2:
                statusStr = "审核通过";
                break;
            case -1:
                statusStr = "审核不通过";
                break;
            default:
                statusStr = "借款已关闭";
                break;
        }
        return statusStr;
    }
}
